﻿using ApplicationBase.Core.Context;
using IdentityService.Domain.Aggregates.PermitAggregate;
using IdentityService.Domain.Repositories;

namespace IdentityService.Domain.Services
{
    public interface IPermitService
    {
        Task<CreatePermitResultModel> CreatePermit(long parentId, string name, string description = "");
        Task<DeletePermitResult> DeleteAsync(long id);
        Task<ModifyPermitResult> ModifyAsync(long id, string name, string description);
    }

    public class PermitService : IPermitService
    {
        private readonly IServiceContext _serviceContext;
        private readonly IPermitRepository _permitRepository;
        public PermitService(IServiceContext serviceContext, IPermitRepository permitRepository)
            => (_serviceContext, _permitRepository) = (serviceContext, permitRepository);

        public async Task<CreatePermitResultModel> CreatePermit(long parentId, string name, string description = "")
        {
            if (!await _permitRepository.CheckExistByIdAsync(parentId))
                return new CreatePermitResultModel() { Result = CreatePermitResult.ParentIdNotFind };

            if (await _permitRepository.CheckExistByNameAsync(name))
                return new CreatePermitResultModel() { Result = CreatePermitResult.NameExist };

            var permit = new Permit(_serviceContext.GenerateId(), name, description) 
                { ParentId = parentId };
            await _permitRepository.AddAsync(permit);

            return new CreatePermitResultModel()
            {
                Result = CreatePermitResult.Success,
                Data = permit
            };
        }

        public async Task<DeletePermitResult> DeleteAsync(long id)
        {
            var permit = await _permitRepository.FindByIdWithChildrenAsync(id);
            if (permit == null) return DeletePermitResult.IdNotFound;
            if (permit.Children.Count > 0) return DeletePermitResult.HasChildrenCanNotDelete;

            _permitRepository.Delete(permit);
            return DeletePermitResult.Success;
        }

        public async Task<ModifyPermitResult> ModifyAsync(long id, string name, string description)
        {
            var permit = await _permitRepository.FindByIdAsync(id);
            if (permit == null) return ModifyPermitResult.IdNotFound;

            if (permit.Name != name && await _permitRepository.CheckExistByNameAsync(name))
                return ModifyPermitResult.NameExist;

            permit.Modify(name, description);
            return ModifyPermitResult.Success;
        }

        public async Task ClearSolitaryPermitAsync()
        {
            while(true)
            {
                var list = await _permitRepository.FindSolitaryRecords();
                if(list == null || list.Count == 0) break;

                _permitRepository.DeleteRangeAndSave(list);
            }
        }
    }

    public enum CreatePermitResult
    {
        Success,
        ParentIdNotFind,
        NameExist
    }

    public class CreatePermitResultModel
    {
        public CreatePermitResult Result { get; set; }
        public Permit? Data { get; set; }
    }

    public enum DeletePermitResult
    {
        Success,
        IdNotFound,
        HasChildrenCanNotDelete
    }

    public enum ModifyPermitResult
    {
        Success,
        IdNotFound,
        NameExist,
    }
}
